import ctypes
import datetime
import glob
import json
import sys
import threading
import tkinter as tk
from queue import Queue
from tkinter import ttk, messagebox, filedialog
import pyautogui
import time
import os
from urllib.parse import quote
import pyperclip
import keyboard
from log_manager import LogManager


class ConfigManager:
    def __init__(self):
        self.config_file = "app_config.json"
        self.default_config = {
            # 软件1设置
            "browser_wait_time": "10",
            "parse_window_wait_time": "60",
            "parse_wait_time": "10",

            # 软件2设置
            "max_parse_wait": "30",
            "max_parse_entry": "20",
            "min_likes_entry": "0",
            "min_comments_entry": "0",
            "min_favorites_entry": "0",
            "min_duration_entry": "0",

            # 通用设置
            "task_interval": "30",
            "base_path": "D:\\Users\\LT08\\Desktop\\闪豆下载器\\",
            "shandou_path": "D:\\Program Files\\Shandou\\闪豆视频下载器.exe",
            "douyin_path": "D:\\Users\\LT08\\Desktop\\抖音视频下载助手1.1.exe",

            # 坐标设置
            "coordinates": {
                # 软件1坐标
                "切换窗口1:": [667, 421],
                "URL输入框:": [727, 452],
                "解析按钮:": [972, 452],
                "浏览器关闭按钮:": [1734, 434],
                "下载按钮:": [1585, 913],
                "浏览按钮:": [1446, 718],
                "文件选择取消按钮:": [1400, 904],
                "路径输入框:": [1227, 713],
                "下载确定按钮:": [1359, 788],
                "解析窗口关闭按钮:": [1625, 516],

                # 软件2坐标
                "切换窗口2:": [988, 335],
                "点击全局设置:": [765, 673],
                "点击更改:": [1745, 388],
                "粘贴文件夹:": [904, 1086],
                "选择文件夹:": [1627, 1120],
                "点击解析搜索:": [762, 564],
                "搜索框:": [938, 387],
                "最大解析数量:": [1551, 529],
                "开始解析:": [1584, 387],
                "作品评论数:": [1474, 461],
                "作品点赞数:": [1467, 496],
                "作品时长秒:": [1298, 491],
                "作品收藏数:": [1641, 492],
                "开始筛选:": [1724, 468],
                "下载筛选:": [1809, 468],
                "下载全部:": [1816, 391],
                "点击确认按钮:": [1300, 766],
                "点击清空列表:": [1711, 530],
                "确认:": [1232, 777]
            }
        }

    def load_config(self):
        """加载配置文件，如果不存在则创建默认配置"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            return self.default_config
        except Exception as e:
            print(f"加载配置文件失败: {str(e)}")
            return self.default_config

    def save_config(self, config):
        """保存配置到文件"""
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=4)
            return True
        except Exception as e:
            print(f"保存配置文件失败: {str(e)}")
            return False


def is_time_in_range(current, start, end):
    """检查当前时间是否在指定范围内"""

    def parse_time(time_str):
        return datetime.datetime.strptime(time_str, '%H:%M').time()

    current_time = parse_time(current)
    start_time = parse_time(start)
    end_time = parse_time(end)

    if start_time <= end_time:
        return start_time <= current_time <= end_time
    else:  # 处理跨午夜的情况
        return current_time >= start_time or current_time <= end_time


def process_directory_name(directory_name):
    """处理目录名，移除空格"""
    return directory_name.replace(" ", "")


class AutoDownloaderGUI:
    def __init__(self, root):
        self.countdown_active = None
        self.root = root
        self.root.title("TikTok视频下载自动化工具")

        # 初始化变量
        self.current_batch_index = 0
        self.stop_flag = False
        self.task_running = False
        self.keywords = []
        self.task_completed = False
        self.schedule_running = False
        self.schedule_thread = None
        self.task_queue = Queue()
        # 创建设置容器（移动到前面）
        self.settings_container = None  # 先初始化为None
        self.config_manager = ConfigManager()

        # 添加日志管理器
        self.log_manager = LogManager()

        # 设置窗口大小和位置
        window_width = 600
        window_height = 850
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        center_x = int(screen_width / 2 - window_width / 2)
        center_y = int(screen_height / 2 - window_height / 2)
        self.root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')

        # 创建主框架
        self.main_frame = ttk.Frame(root, padding="5")
        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 创建界面元素
        self.create_top_controls()
        self.create_notebook()
        self.create_status_bar()

        # 设置ESC键监听
        keyboard.on_press_key('esc', self.stop_execution)

        # 加载保存的设置
        self.load_saved_settings()

        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def on_closing(self):
        """窗口关闭时的处理"""
        self.save_current_settings()
        self.root.destroy()

    def create_top_controls(self):
        """创建顶部控制区域"""
        top_frame = ttk.Frame(self.main_frame)
        top_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=5)

        ttk.Label(top_frame, text="按 ESC 键停止执行",
                  font=('宋体', 10, 'bold'),
                  foreground='red').pack(side=tk.LEFT, padx=5)

        self.is_topmost = tk.BooleanVar()
        ttk.Checkbutton(top_frame, text="窗口置顶",
                        variable=self.is_topmost,
                        command=lambda: self.root.attributes('-topmost',
                                                             self.is_topmost.get())
                        ).pack(side=tk.RIGHT, padx=5)

        # 操作按钮
        buttons_frame = ttk.Frame(self.main_frame)
        buttons_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=5)

        buttons = [
            ("导入关键词", self.import_keywords),
            ("启动下载器", self.start_downloader),
            ("开始单个任务", self.start_automation),
            ("开始批量处理", self.start_batch_automation)
        ]

        for text, command in buttons:
            ttk.Button(buttons_frame, text=text, command=command).pack(side=tk.LEFT, padx=5)

    def create_notebook(self):
        """创建标签页"""
        notebook = ttk.Notebook(self.main_frame)
        notebook.grid(row=3, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5)

        # 调度设置页
        schedule_frame = ttk.Frame(notebook, padding="5")
        notebook.add(schedule_frame, text="调度设置")
        self.create_schedule_settings(schedule_frame)

        # 基本设置页
        basic_frame = ttk.Frame(notebook, padding="5")
        notebook.add(basic_frame, text="基本设置")
        self.create_basic_settings(basic_frame)

        # 坐标设置页
        coords_frame = ttk.Frame(notebook, padding="5")
        notebook.add(coords_frame, text="坐标设置")
        self.create_coords_settings(coords_frame)

        # 任务列表页
        task_frame = ttk.Frame(notebook, padding="5")
        notebook.add(task_frame, text="任务列表")
        self.create_task_list(task_frame)

    def create_basic_settings(self, parent):
        """创建基本设置页面"""
        # 添加日志设置框架
        log_frame = ttk.LabelFrame(self.settings_container, text="日志设置", padding="5")

        # 创建日志开关
        self.log_enabled = tk.BooleanVar(value=False)
        ttk.Checkbutton(log_frame, text="启用日志记录",
                        variable=self.log_enabled,
                        command=self.toggle_logging).pack(side=tk.LEFT, padx=5)

        # 创建日志保留天数设置
        ttk.Label(log_frame, text="保留天数:").pack(side=tk.LEFT, padx=5)
        self.log_days = ttk.Entry(log_frame, width=5)
        self.log_days.insert(0, "7")
        self.log_days.pack(side=tk.LEFT, padx=5)

        # 添加清理日志按钮
        ttk.Button(log_frame, text="清理旧日志",
                   command=self.clean_logs).pack(side=tk.LEFT, padx=5)

        # 将日志设置框架添加到设置容器中
        log_frame.grid(row=3, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

        # 添加软件选择
        software_frame = ttk.LabelFrame(parent, text="软件选择", padding="5")
        software_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

        self.software_var = tk.StringVar(value="software1")
        self.alternate_execution = tk.BooleanVar(value=False)

        def on_selection_change(*args):
            # 确保在交替执行模式下也能正确触发界面更新
            self.update_settings_visibility()

            # 为软件选择变量添加跟踪

        self.software_var.trace_add('write', on_selection_change)

        # 为交替执行选项添加回调
        def on_alternate_change():
            # 当切换交替执行状态时也更新界面
            self.update_settings_visibility()

        # 创建单选按钮和复选框
        ttk.Radiobutton(software_frame, text="闪豆视频下载器(tiktok)",
                        variable=self.software_var,
                        value="software1").pack(side=tk.LEFT, padx=10)
        ttk.Radiobutton(software_frame, text="闪豆视频下载器(抖音)",
                        variable=self.software_var,
                        value="software3").pack(side=tk.LEFT, padx=10)
        ttk.Radiobutton(software_frame, text="抖音视频下载助手",
                        variable=self.software_var,
                        value="software2").pack(side=tk.LEFT, padx=10)
        ttk.Checkbutton(software_frame, text="交替执行",
                        variable=self.alternate_execution,
                        command=on_alternate_change).pack(side=tk.LEFT, padx=10)

        # 创建设置容器
        self.settings_container = ttk.Frame(parent)
        self.settings_container.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E))

        # 创建软件1特定设置
        self.software1_frame = ttk.LabelFrame(self.settings_container, text="闪豆下载器设置", padding="5")
        settings1 = [
            ("浏览器等待时间(秒):", "browser_wait_time", 10, "10"),
            ("解析窗口关闭操作等待时间(秒):", "parse_window_wait_time", 10, "60"),
            ("解析等待时间(秒):", "parse_wait_time", 10, "10")
        ]

        for i, (label, attr, width, default) in enumerate(settings1):
            ttk.Label(self.software1_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
            entry = ttk.Entry(self.software1_frame, width=width)
            setattr(self, attr, entry)
            entry.grid(row=i, column=1, sticky=tk.W, pady=2)
            if default:
                entry.insert(0, default)

        # 创建软件2特定设置
        self.software2_frame = ttk.LabelFrame(self.settings_container, text="抖音下载助手设置", padding="5")

        # 筛选条件设置
        filters = [
            ("最大解析时间:", "max_parse_wait", "30"),
            ("最大解析数量:", "max_parse_entry", "20"),
            ("最小点赞数:", "min_likes_entry", "0"),
            ("最小评论数:", "min_comments_entry", "0"),
            ("最小收藏数:", "min_favorites_entry", "0"),
            ("最小时长(秒):", "min_duration_entry", "0")
        ]

        for i, (label, attr, default) in enumerate(filters):
            ttk.Label(self.software2_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
            entry = ttk.Entry(self.software2_frame, width=10)
            setattr(self, attr, entry)
            entry.grid(row=i, column=1, sticky=tk.W, pady=2, padx=5)
            if default:
                entry.insert(0, default)

        # 通用设置
        self.common_frame = ttk.LabelFrame(self.settings_container, text="通用设置", padding="5")
        common_settings = [
            ("单个关键词任务:", "keyword_entry", 40, None),
            ("任务间隔时间(秒):", "task_interval", 10, "30"),
            ("基础下载路径:", "base_path_entry", 40, "D:\\Users\\LT08\\Desktop\\闪豆下载器\\"),
            ("闪豆下载器路径:", "shandou", 40, "D:\\Program Files\\Shandou\\闪豆视频下载器.exe"),
            ("抖音视频助手路径:", "douyin", 40, "D:\\Users\\LT08\\Desktop\\抖音视频下载助手1.1.exe")
        ]

        for i, (label, attr, width, default) in enumerate(common_settings):
            ttk.Label(self.common_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
            entry = ttk.Entry(self.common_frame, width=width)
            setattr(self, attr, entry)
            entry.grid(row=i, column=1, sticky=tk.W, pady=2)
            if default:
                entry.insert(0, default)

        # 初始显示设置
        self.update_settings_visibility()

    def toggle_logging(self):
        """切换日志记录状态"""
        self.log_manager.enabled = self.log_enabled.get()
        try:
            self.log_manager.max_log_days = int(self.log_days.get())
        except ValueError:
            messagebox.showwarning("警告", "日志保留天数必须是数字，已设为默认值7天")
            self.log_days.delete(0, tk.END)
            self.log_days.insert(0, "7")
            self.log_manager.max_log_days = 7

    def clean_logs(self):
        """清理旧日志"""
        if messagebox.askyesno("确认", "确定要清理超过保留天数的日志文件吗？"):
            self.log_manager.clean_old_logs()
            messagebox.showinfo("完成", "日志清理完成")

    def update_settings_visibility(self):
        """更新设置的可见性"""
        try:
            # 先将所有特定设置从网格中移除
            for frame in [self.software1_frame, self.software2_frame]:
                frame.grid_remove()

            # 确保通用设置始终显示
            self.common_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

            # 根据当前选择的软件显示对应设置
            current_software = self.software_var.get()
            if current_software == "software1":
                self.software1_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
            elif current_software == "software2":  # software2
                self.software2_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
            elif current_software == "software3":  # software2
                self.software1_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)

            # 强制更新界面
            self.settings_container.update_idletasks()
        except Exception as e:
            print(f"更新设置界面时出错: {str(e)}")

    def create_coords_settings(self, parent):
        """创建坐标设置页面"""
        # 创建分页标签
        coords_notebook = ttk.Notebook(parent)
        coords_notebook.pack(fill='both', expand=True)

        # 软件1坐标设置
        sw1_frame = ttk.Frame(coords_notebook, padding="5")
        coords_notebook.add(sw1_frame, text="闪豆下载器")
        self.create_software1_coords(sw1_frame)

        # 软件2坐标设置
        sw2_frame = ttk.Frame(coords_notebook, padding="5")
        coords_notebook.add(sw2_frame, text="抖音下载助手")
        self.create_software2_coords(sw2_frame)

    def create_software1_coords(self, parent):
        """创建软件1的坐标设置"""
        headers = ["坐标项", "X坐标", "Y坐标", "获取"]
        for i, header in enumerate(headers):
            ttk.Label(parent, text=header).grid(row=0, column=i, padx=5, pady=5)

        coord_labels = [
            "切换窗口1:", "URL输入框(tiktok):", "关键词输入框(抖音):", "解析按钮(tiktok):", "搜索按钮(抖音):", "浏览器关闭按钮:", "下载按钮:",
            "浏览按钮:", "文件选择取消按钮:", "路径输入框:",
            "下载确定按钮:", "解析窗口关闭按钮:"
        ]

        self.coord_entries = {}
        for i, label in enumerate(coord_labels, 1):
            ttk.Label(parent, text=label).grid(row=i, column=0, sticky=tk.W, padx=5)
            x_entry = ttk.Entry(parent, width=8)
            y_entry = ttk.Entry(parent, width=8)
            x_entry.grid(row=i, column=1, padx=5)
            y_entry.grid(row=i, column=2, padx=5)
            self.coord_entries[label] = (x_entry, y_entry)
            ttk.Button(parent, text="获取",
                       command=lambda l=label: self.get_position(l)
                       ).grid(row=i, column=3, padx=5)

    def create_software2_coords(self, parent):
        """创建软件2的坐标设置"""
        headers = ["坐标项", "X坐标", "Y坐标", "获取"]
        for i, header in enumerate(headers):
            ttk.Label(parent, text=header).grid(row=0, column=i, padx=5, pady=5)

        coord_labels = [
            "切换窗口2:", "点击全局设置:", "点击更改:", "粘贴文件夹:", "关闭下拉:", "选择文件夹:", "点击解析搜索:", "搜索框:",
            "最大解析数量:", "开始解析:", "作品评论数:",
            "作品点赞数:", "作品时长秒:", "作品收藏数:", "开始筛选:",
            "下载筛选:", "下载全部:", "点击确认按钮:", "点击清空列表:", "确认:"
        ]

        for i, label in enumerate(coord_labels, 1):
            ttk.Label(parent, text=label).grid(row=i, column=0, sticky=tk.W, padx=5)
            x_entry = ttk.Entry(parent, width=8)
            y_entry = ttk.Entry(parent, width=8)
            x_entry.grid(row=i, column=1, padx=5)
            y_entry.grid(row=i, column=2, padx=5)
            self.coord_entries[label] = (x_entry, y_entry)
            ttk.Button(parent, text="获取",
                       command=lambda l=label: self.get_position(l)
                       ).grid(row=i, column=3, padx=5)

        # 设置默认坐标值
        default_coords = {
            # 软件1默认坐标
            "切换窗口1:": (667, 421),
            "URL输入框(tiktok):": (727, 452),
            "关键词输入框(抖音):": (1234, 452),
            "解析按钮(tiktok):": (1139, 454),
            "搜索按钮(抖音):": (1456, 454),
            "浏览器关闭按钮:": (1734, 434),
            "下载按钮:": (1585, 913),
            "浏览按钮:": (1446, 718),
            "文件选择取消按钮:": (1400, 904),
            "路径输入框:": (1227, 713),
            "下载确定按钮:": (1359, 788),
            "解析窗口关闭按钮:": (1625, 516),
            # 软件2默认坐标
            "切换窗口2:": (988, 335),
            "点击全局设置:": (765, 673),
            "点击更改:": (1745, 388),
            "粘贴文件夹:": (904, 1086),
            "关闭下拉:": (669, 1100),
            "选择文件夹:": (1627, 1120),
            "点击解析搜索:": (762, 564),
            "搜索框:": (938, 387),
            "最大解析数量:": (1551, 529),
            "开始解析:": (1584, 387),
            "作品评论数:": (1474, 461),
            "作品点赞数:": (1467, 496),
            "作品时长秒:": (1298, 491),
            "作品收藏数:": (1641, 492),
            "开始筛选:": (1724, 468),
            "下载筛选:": (1809, 468),
            "下载全部:": (1816, 391),
            "点击确认按钮:": (1300, 766),
            "点击清空列表:": (1711, 530),
            "确认:": (1232, 777),
        }

        for label, (x, y) in default_coords.items():
            if label in self.coord_entries:
                self.coord_entries[label][0].insert(0, str(x))
                self.coord_entries[label][1].insert(0, str(y))

    def save_current_settings(self):
        """保存当前所有设置"""
        config = {
            # 软件1设置
            "browser_wait_time": self.browser_wait_time.get(),
            "parse_window_wait_time": self.parse_window_wait_time.get(),
            "parse_wait_time": self.parse_wait_time.get(),

            # 软件2设置
            "max_parse_wait": self.max_parse_wait.get(),
            "max_parse_entry": self.max_parse_entry.get(),
            "min_likes_entry": self.min_likes_entry.get(),
            "min_comments_entry": self.min_favorites_entry.get(),
            "min_favorites_entry": self.min_favorites_entry.get(),
            "min_duration_entry": self.min_duration_entry.get(),

            # 通用设置
            "task_interval": self.task_interval.get(),
            "base_path": self.base_path_entry.get(),
            "shandou_path": self.shandou.get(),
            "douyin_path": self.douyin.get(),

            # 坐标设置
            "coordinates": {
                label: [
                    int(self.coord_entries[label][0].get()),
                    int(self.coord_entries[label][1].get())
                ]
                for label in self.coord_entries
            }
        }

        self.config_manager.save_config(config)

    def load_saved_settings(self):
        """加载保存的设置"""
        config = self.config_manager.load_config()

        # 加载软件1设置
        self.browser_wait_time.delete(0, tk.END)
        self.browser_wait_time.insert(0, config.get("browser_wait_time", "10"))
        self.parse_window_wait_time.delete(0, tk.END)
        self.parse_window_wait_time.insert(0, config.get("parse_window_wait_time", "60"))
        self.parse_wait_time.delete(0, tk.END)
        self.parse_wait_time.insert(0, config.get("parse_wait_time", "10"))

        # 加载软件2设置
        self.max_parse_wait.delete(0, tk.END)
        self.max_parse_wait.insert(0, config.get("max_parse_wait", "30"))
        self.max_parse_entry.delete(0, tk.END)
        self.max_parse_entry.insert(0, config.get("max_parse_entry", "20"))
        self.min_likes_entry.delete(0, tk.END)
        self.min_likes_entry.insert(0, config.get("min_likes_entry", "0"))
        self.min_comments_entry.delete(0, tk.END)
        self.min_comments_entry.insert(0, config.get("min_comments_entry", "0"))
        self.min_favorites_entry.delete(0, tk.END)
        self.min_favorites_entry.insert(0, config.get("min_favorites_entry", "0"))
        self.min_duration_entry.delete(0, tk.END)
        self.min_duration_entry.insert(0, config.get("min_duration_entry", "0"))

        # 加载通用设置
        self.task_interval.delete(0, tk.END)
        self.task_interval.insert(0, config.get("task_interval", "30"))
        self.base_path_entry.delete(0, tk.END)
        self.base_path_entry.insert(0, config.get("base_path", "D:\\Users\\LT08\\Desktop\\闪豆下载器\\"))
        self.shandou.delete(0, tk.END)
        self.shandou.insert(0, config.get("shandou_path", "D:\\Program Files\\Shandou\\闪豆视频下载器.exe"))
        self.douyin.delete(0, tk.END)
        self.douyin.insert(0, config.get("douyin_path", "D:\\Users\\LT08\\Desktop\\抖音视频下载助手1.1.exe"))

        # 加载坐标设置
        coordinates = config.get("coordinates", {})
        for label, entry_tuple in self.coord_entries.items():
            if label in coordinates:
                x, y = coordinates[label]
                entry_tuple[0].delete(0, tk.END)
                entry_tuple[0].insert(0, str(x))
                entry_tuple[1].delete(0, tk.END)
                entry_tuple[1].insert(0, str(y))

    def create_task_list(self, parent):
        """创建任务列表页面"""
        # 添加滚动条
        scrollbar = ttk.Scrollbar(parent)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 任务列表显示
        self.task_list = tk.Text(parent, height=25, width=50,
                                 yscrollcommand=scrollbar.set)
        self.task_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.config(command=self.task_list.yview)

    def create_status_bar(self):
        """创建状态栏"""
        self.status_var = tk.StringVar(value="就绪")
        status_label = ttk.Label(self.main_frame, textvariable=self.status_var)
        status_label.grid(row=2, column=0, sticky=(tk.W, tk.E), pady=5)

    def create_schedule_settings(self, parent):
        """创建调度设置页面"""
        # 软件1调度设置
        sw1_frame = ttk.LabelFrame(parent, text="闪豆视频下载器调度", padding="5")
        sw1_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=5, padx=5)

        ttk.Label(sw1_frame, text="执行时间段:").grid(row=0, column=0, sticky=tk.W)
        self.sw1_start_time = ttk.Entry(sw1_frame, width=10)
        self.sw1_start_time.insert(0, "09:00")
        self.sw1_start_time.grid(row=0, column=1, padx=5)

        ttk.Label(sw1_frame, text="至").grid(row=0, column=2)
        self.sw1_end_time = ttk.Entry(sw1_frame, width=10)
        self.sw1_end_time.insert(0, "12:00")
        self.sw1_end_time.grid(row=0, column=3, padx=5)

        # 软件2调度设置
        sw2_frame = ttk.LabelFrame(parent, text="抖音视频下载助手调度", padding="5")
        sw2_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=5, padx=5)

        ttk.Label(sw2_frame, text="执行时间段:").grid(row=0, column=0, sticky=tk.W)
        self.sw2_start_time = ttk.Entry(sw2_frame, width=10)
        self.sw2_start_time.insert(0, "14:00")
        self.sw2_start_time.grid(row=0, column=1, padx=5)

        ttk.Label(sw2_frame, text="至").grid(row=0, column=2)
        self.sw2_end_time = ttk.Entry(sw2_frame, width=10)
        self.sw2_end_time.insert(0, "18:00")
        self.sw2_end_time.grid(row=0, column=3, padx=5)

        # 调度控制按钮
        control_frame = ttk.Frame(parent)
        control_frame.grid(row=2, column=0, sticky=(tk.W, tk.E), pady=10)

        ttk.Button(control_frame, text="启动调度",
                   command=self.start_schedule).pack(side=tk.LEFT, padx=5)
        ttk.Button(control_frame, text="停止调度",
                   command=self.stop_schedule).pack(side=tk.LEFT, padx=5)

    def start_schedule(self):
        """启动调度任务"""
        if self.schedule_running:
            messagebox.showinfo("提示", "调度任务已在运行中")
            return

        try:
            # 验证时间格式并转换为时间对象
            for time_entry in [self.sw1_start_time, self.sw1_end_time,
                               self.sw2_start_time, self.sw2_end_time]:
                time.strptime(time_entry.get(), '%H:%M')

            # 记录调度时间
            self.log_manager.write_log(
                f"启动调度任务 - 软件1: {self.sw1_start_time.get()}-{self.sw1_end_time.get()}, " +
                f"软件2: {self.sw2_start_time.get()}-{self.sw2_end_time.get()}", "调度")

            self.schedule_running = True
            self.schedule_thread = threading.Thread(target=self.schedule_loop, daemon=True)
            self.schedule_thread.start()
            self.status_var.set("调度任务已启动")
        except ValueError:
            messagebox.showerror("错误", "时间格式错误，请使用HH:MM格式")

    def stop_schedule(self):
        """停止调度任务"""
        if self.schedule_running:
            self.schedule_running = False
            self.log_manager.write_log("停止调度任务", "调度")
            self.status_var.set("调度任务已停止")
        else:
            self.status_var.set("没有正在运行的调度任务")

    def schedule_loop(self):
        """调度循环"""
        last_executed_hour = None  # 用于跟踪上次执行的小时
        current_schedule = None  # 记录当前正在执行的调度（软件1或软件2）

        while self.schedule_running:
            try:
                current_time = datetime.datetime.now()
                current_str = current_time.strftime('%H:%M')
                current_hour = current_time.hour

                # 检查任务是否正在执行
                if self.task_running:
                    self.log_manager.write_log(f"当前有任务正在执行，等待完成... 当前时间: {current_str}", "调度")
                    time.sleep(30)
                    continue

                # 检查软件1的时间段
                in_sw1_range = is_time_in_range(current_str,
                                                self.sw1_start_time.get(),
                                                self.sw1_end_time.get())

                # 检查软件2的时间段
                in_sw2_range = is_time_in_range(current_str,
                                                self.sw2_start_time.get(),
                                                self.sw2_end_time.get())

                # 检查是否需要结束当前调度
                if current_schedule:
                    if (current_schedule == "software1" and not in_sw1_range) or \
                            (current_schedule == "software2" and not in_sw2_range):
                        self.log_manager.write_log(f"超出调度时间范围，停止当前调度: {current_schedule}", "调度")
                        self.stop_current_task()
                        current_schedule = None
                        last_executed_hour = None

                # 启动新的调度任务
                if not current_schedule:  # 只在没有当前调度时检查新调度
                    if in_sw1_range and last_executed_hour != current_hour:
                        self.log_manager.write_log(f"开始软件1调度执行，时间: {current_str}", "调度")
                        self.software_var.set("software1")
                        current_schedule = "software1"
                        self.root.after(0, lambda: self._safe_start_batch())
                        last_executed_hour = current_hour

                    elif in_sw2_range and last_executed_hour != current_hour:
                        self.log_manager.write_log(f"开始软件2调度执行，时间: {current_str}", "调度")
                        self.software_var.set("software2")
                        current_schedule = "software2"
                        self.root.after(0, lambda: self._safe_start_batch())
                        last_executed_hour = current_hour

                time.sleep(30)  # 每30秒检查一次
            except Exception as e:
                error_msg = f"调度错误: {str(e)}"
                self.log_manager.write_log(error_msg, "调度错误")
                self.status_var.set(error_msg)
                time.sleep(60)

    def stop_current_task(self):
        """停止当前正在执行的任务"""
        if self.task_running:
            self.log_manager.write_log("正在停止当前任务...", "调度")
            self.stop_flag = True
            # 等待任务停止
            retry_count = 0
            while self.task_running and retry_count < 10:
                time.sleep(1)
                retry_count += 1

            if self.task_running:
                self.log_manager.write_log("强制停止任务", "调度")
                self.task_running = False
            else:
                self.log_manager.write_log("任务已正常停止", "调度")

            self.stop_flag = False

    def _safe_start_batch(self):
        """安全地在主线程中启动批处理"""
        try:
            if not self.keywords:
                self.log_manager.write_log("调度执行失败：没有导入关键词", "调度错误")
                return
            # 调用批处理时传入auto_confirm=True
            self.start_batch_automation(auto_confirm=True)
        except Exception as e:
            self.log_manager.write_log(f"启动批处理时出错: {str(e)}", "调度错误")

    def stop_execution(self, _):
        """停止执行的回调函数"""
        self.stop_flag = True
        self.countdown_active = False  # 停止倒计时
        self.status_var.set("用户终止执行！")
        self.root.update()

    def import_keywords(self):
        """导入关键词文件"""
        filename = filedialog.askopenfilename(
            title="选择关键词文件",
            filetypes=(("文本文件", "*.txt"), ("所有文件", "*.*"))
        )
        if filename:
            try:
                self.keywords = []  # 清空现有关键词
                current_level1 = None
                current_level2 = None
                base_path = self.base_path_entry.get()

                with open(filename, 'r', encoding='utf-8') as f:
                    for line in f:
                        line = line.strip()
                        if not line:
                            continue

                        if line.startswith('# '):
                            # 一级目录
                            current_level1 = line[2:].strip()
                            current_level1_processed = process_directory_name(current_level1)
                            current_level2 = None
                            # 创建一级目录
                            level1_path = os.path.join(base_path, current_level1_processed)
                            os.makedirs(level1_path, exist_ok=True)

                        elif line.startswith('## '):
                            # 二级目录
                            if not current_level1:
                                raise ValueError("发现二级目录但没有对应的一级目录")
                            current_level2 = line[3:].strip()
                            current_level2_processed = process_directory_name(current_level2)
                            # 创建二级目录
                            level2_path = os.path.join(
                                base_path,
                                process_directory_name(current_level1),
                                current_level2_processed
                            )
                            os.makedirs(level2_path, exist_ok=True)

                        elif '|' in line:
                            # 关键词行
                            if not current_level1:
                                raise ValueError("发现关键词但没有对应的目录")

                            parts = line.split('|')
                            if len(parts) == 2:
                                kw1, kw2 = parts[0].strip(), parts[1].strip()

                                # 构建目录路径，使用处理后的目录名
                                if current_level2:
                                    # 如果有二级目录，使用完整的层级路径
                                    dir_path = os.path.join(
                                        process_directory_name(current_level1),
                                        process_directory_name(current_level2)
                                    )
                                else:
                                    # 否则只使用一级目录
                                    dir_path = process_directory_name(current_level1)

                                # 存储原始关键词和处理后的目录路径
                                self.keywords.append((kw1, kw2, dir_path))

                # 更新任务列表显示，显示原始关键词而不是处理后的版本
                self.task_list.delete(1.0, tk.END)
                for i, (kw1, kw2, dir_path) in enumerate(self.keywords, 1):
                    # 在显示时保持原始格式，包括空格
                    self.task_list.insert(tk.END, f"{i}. [{dir_path}] 软件1: {kw1} | 软件2: {kw2}\n")

                messagebox.showinfo("成功", f"成功导入 {len(self.keywords)} 个关键词对")
            except Exception as e:
                messagebox.showerror("错误", f"导入文件失败: {str(e)}")

    def _get_download_path(self, keyword):
        """
        获取下载路径，确保所有组件都没有空格，
        并在需要时创建目录
        """
        try:
            if isinstance(keyword, tuple):
                base_path = self.base_path_entry.get()
                dir_path = keyword[2]  # 已经是处理过的目录路径（无空格）

                # 始终使用软件1的关键词，并去除空格
                search_term = process_directory_name(keyword[0])  # 软件1的关键词

                # 构建完整路径
                full_path = os.path.join(base_path, dir_path, search_term)
            else:
                # 单个关键词的情况
                processed_keyword = process_directory_name(keyword)
                full_path = os.path.join(self.base_path_entry.get(), processed_keyword)

            # 规范化路径
            full_path = os.path.normpath(full_path)

            # 检查目录是否存在，不存在则创建
            if not os.path.exists(full_path):
                self.log_manager.write_log(f"创建目录: {full_path}", "路径处理")
                os.makedirs(full_path, exist_ok=True)
            else:
                self.log_manager.write_log(f"目录已存在: {full_path}", "路径处理")

            return full_path

        except Exception as e:
            self.log_manager.write_log(f"路径处理错误: {str(e)}", "错误")
            raise e

    def get_position(self, label):
        """获取鼠标位置并更新对应坐标输入框"""
        self.status_var.set(f"3秒后获取{label}坐标，请将鼠标移动到目标位置...")
        self.root.update()
        time.sleep(3)
        x, y = pyautogui.position()
        self.coord_entries[label][0].delete(0, tk.END)
        self.coord_entries[label][1].delete(0, tk.END)
        self.coord_entries[label][0].insert(0, str(x))
        self.coord_entries[label][1].insert(0, str(y))
        self.status_var.set(f"{label}坐标已更新: ({x}, {y})")
        self.save_current_settings()  # 保存更新后的设置

    def get_coords(self, label):
        """获取指定标签的坐标值"""
        x = int(self.coord_entries[label][0].get())
        y = int(self.coord_entries[label][1].get())
        return x, y

    def wait_and_click(self, label, wait_time=0.5):
        """等待指定时间后点击指定位置"""
        x, y = self.get_coords(label)
        pyautogui.moveTo(x, y)
        time.sleep(0.2)
        pyautogui.click()
        time.sleep(wait_time)

    def start_downloader(self):
        """启动下载器"""
        try:
            # 获取当前软件选择和交替执行状态
            current_software = self.software_var.get()
            is_alternate = self.alternate_execution.get()

            if current_software == "software1" or current_software == "software3" or is_alternate:
                # 启动闪豆视频下载器
                os.startfile(self.shandou.get())
                self.status_var.set("正在启动闪豆视频下载器...")

            if current_software == "software2" or is_alternate:
                # 延迟1秒后启动抖音视频下载助手
                if current_software == "software1" or is_alternate:
                    # 如果是交替执行模式或先启动软件1，需要延迟启动第二个软件
                    self.root.after(1000, lambda: os.startfile(self.douyin.get()))
                    if is_alternate:
                        self.status_var.set("正在启动两个下载器...")
                else:
                    # 如果只选择了软件2，直接启动
                    os.startfile(self.douyin.get())
                    self.status_var.set("正在启动抖音视频下载助手...")

            # 启动延迟后返回 True
            self.root.after(500, lambda: self.status_var.set("等待下载器初始化..."))
            return True
        except Exception as e:
            messagebox.showerror("错误", f"启动下载器失败: {str(e)}")
            return False

    def wait_for_downloader(self, seconds, next_step):
        """等待下载器初始化完成"""
        # 添加倒计时状态追踪
        if hasattr(self, 'countdown_active') and self.countdown_active:
            # 如果已经有倒计时在运行，直接返回
            return

        self.countdown_active = True

        def countdown(remaining):
            if self.stop_flag or not self.countdown_active:
                self.countdown_active = False
                return

            if remaining <= 0:
                self.countdown_active = False
                next_step()
                return

            self.status_var.set(f"等待下载器初始化... ({remaining}秒)")
            self.root.update()
            self.root.after(1000, lambda: countdown(remaining - 1))

        # 确保在启动延迟后开始倒计时
        self.root.after(1500, lambda: countdown(seconds))

    def wait_with_counter(self, seconds, next_step, message="等待中", keyword=None):
        """非阻塞等待函数"""
        if seconds <= 0:
            next_step()
            return

        display_message = f"{message}... ({seconds}秒)"
        if keyword:
            display_message = f"[{keyword}] {display_message}"
        self.status_var.set(display_message)
        self.root.update()

        if self.stop_flag:
            self.stop_flag = False
            raise Exception("用户终止执行")

        self.root.after(1000, lambda: self.wait_with_counter(seconds - 1, next_step, message, keyword))

    def update_task_list_status(self, index, keyword_tuple, success=True):
        """更新任务列表中的任务状态"""
        try:
            current_content = self.task_list.get(1.0, tk.END).split('\n')
            status = "✓" if success else "✗"
            # 从元组中获取显示用的信息
            if isinstance(keyword_tuple, tuple):
                kw1, kw2, dir_path = keyword_tuple
                display_text = f"{index + 1}. [{status}] [{dir_path}] 软件1: {kw1} | 软件2: {kw2}"
            else:
                display_text = f"{index + 1}. [{status}] {keyword_tuple}"

            current_content[index] = display_text
            self.task_list.delete(1.0, tk.END)
            self.task_list.insert(1.0, '\n'.join(current_content))
            self.task_list.see(f"{index + 1}.0")
            self.task_list.update()
        except Exception as e:
            print(f"更新任务列表失败: {str(e)}")

    def start_automation(self, keyword=None):
        """执行自动化流程"""
        try:
            if self.task_running:
                return False

            self.task_running = True
            self.task_completed = False
            self.stop_flag = False

            # 处理关键词
            if keyword is None:
                # 单个任务模式
                current_keyword = self.keyword_entry.get()
            else:
                # 批量处理模式，保持元组格式
                current_keyword = keyword

            if not current_keyword:
                messagebox.showerror("错误", "请输入搜索关键词")
                self.task_running = False
                return False

            # 记录当前任务的执行状态
            if not hasattr(self, 'current_executions'):
                self.current_executions = {}

            # 使用原始的keyword作为键
            task_key = keyword if isinstance(keyword, tuple) else current_keyword
            if task_key not in self.current_executions:
                self.current_executions[task_key] = set()

            # 根据交替执行选项决定执行流程
            if self.alternate_execution.get():
                # 如果需要交替执行
                if len(self.current_executions[task_key]) == 0:
                    # 第一次执行，用软件1
                    self.software_var.set("software1")
                    success = self.run_software1_automation(current_keyword)
                    if success:
                        self.current_executions[task_key].add("software1")
                    return success
                elif len(self.current_executions[task_key]) == 1:
                    # 第二次执行，用软件2
                    self.software_var.set("software2")
                    success = self.run_software2_automation(current_keyword)
                    if success:
                        self.current_executions[task_key].add("software2")
                    return success
                else:
                    # 两个软件都执行过了
                    self.task_running = False
                    return True
            else:
                # 不需要交替执行，按照选择的软件执行
                if self.software_var.get() == "software1" or self.software_var.get() == "software3":
                    return self.run_software1_automation(current_keyword)
                else:
                    return self.run_software2_automation(current_keyword)

        except Exception as e:
            self.task_running = False
            if str(e) == "用户终止执行":
                display_keyword = keyword[0] if isinstance(keyword, tuple) else keyword
                self.status_var.set(f"[{display_keyword}] 已停止执行")
            else:
                messagebox.showerror("错误", f"自动化过程出错: {str(e)}")
                display_keyword = keyword[0] if isinstance(keyword, tuple) else keyword
                self.status_var.set(f"[{display_keyword}] 执行出错")
            return False

    def run_software1_automation(self, keyword):
        """闪豆视频下载器的自动化流程"""

        def log_debug(message):
            """输出调试信息到文件"""
            self.log_manager.write_log(message, "软件1")

        def get_display_keyword():
            """获取用于显示的关键词"""
            # 根据软件选择返回不同的关键词
            if self.software_var.get() == "software3":  # 抖音模式
                return keyword[1] if isinstance(keyword, tuple) else keyword
            return keyword[0] if isinstance(keyword, tuple) else keyword

        def task_completion():
            """任务完成后的处理"""
            self.task_running = False
            self.task_completed = True
            current_keyword = get_display_keyword()
            self.status_var.set(f"✓ 完成处理关键词: {current_keyword}")
            log_debug("任务完成")

        # 构建URL
        base_url = "https://www.tiktok.com/search?q="
        search_term = get_display_keyword()
        encoded_term = search_term.replace(" ", "%20")
        full_url = base_url + encoded_term

        log_debug(f"原始关键词: {keyword}")
        log_debug(f"搜索词: {search_term}")
        if self.software_var.get() != "software3":  # 非抖音模式才记录URL
            log_debug(f"编码后的URL: {full_url}")

        def step0():
            """切换窗口1"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 切换窗口...")
            log_debug("切换窗口")
            self.wait_and_click("切换窗口1:")
            self.root.after(1000, step1)

        def step1():
            """输入URL步骤"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 准备搜索...")

            if self.software_var.get() == "software3":  # 抖音模式
                log_debug("输入抖音搜索关键词")
                self.wait_and_click("关键词输入框(抖音):")  # 使用相同坐标
                pyautogui.hotkey('ctrl', 'a')
                pyautogui.press('backspace')
                search_text = get_display_keyword()  # 使用中文关键词
                pyperclip.copy(search_text)
                log_debug(f"输入抖音关键词: {search_text}")
            else:  # tiktok模式
                log_debug("输入tiktok搜索URL")
                self.wait_and_click("URL输入框(tiktok):")
                pyautogui.hotkey('ctrl', 'a')
                pyautogui.press('backspace')
                pyperclip.copy(full_url)
                log_debug(f"输入URL: {full_url}")

            pyautogui.hotkey('ctrl', 'v')
            self.root.after(1000, step2)

        def step2():
            """点击解析按钮"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 开始解析...")
            if self.software_var.get() == "software3":  # 抖音模式
                log_debug("点击抖音搜索按钮")
                self.wait_and_click("搜索按钮(抖音):")
            else:  # tiktok模式
                log_debug("点击tiktok解析按钮")
                self.wait_and_click("解析按钮(tiktok):")

            browser_wait = int(self.browser_wait_time.get())
            self.wait_with_counter(browser_wait, step3, "等待关闭浏览器窗口", current_keyword)

        def step3():
            """关闭浏览器窗口"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 关闭浏览器窗口...")
            log_debug("关闭浏览器窗口")
            self.wait_and_click("浏览器关闭按钮:")
            parse_wait = int(self.parse_wait_time.get())
            self.wait_with_counter(parse_wait, step4, "等待解析完成", current_keyword)

        def step4():
            """点击下载按钮"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 准备下载...")
            log_debug("点击下载按钮")
            self.wait_and_click("下载按钮:")
            self.root.after(1000, step5)

        def step5():
            """设置下载路径"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 设置下载路径...")
            log_debug("点击浏览按钮")
            self.wait_and_click("浏览按钮:")
            self.root.after(1000, step6)

        def step6():
            """确认文件夹选择"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 确认文件夹选择...")
            log_debug("确认文件夹选择")
            self.wait_and_click("文件选择取消按钮:")
            self.root.after(1000, step7)

        def step7():
            """输入下载路径"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 输入下载路径...")
            self.wait_and_click("路径输入框:")

            try:
                target_path = self._get_download_path(keyword)
                log_debug(f"最终路径: {target_path}")
                pyperclip.copy(target_path)
                pyautogui.hotkey('ctrl', 'a')
                pyautogui.press('backspace')
                pyautogui.hotkey('ctrl', 'v')
            except Exception as e:
                log_debug(f"路径设置错误: {str(e)}")
                raise e

            self.root.after(1000, step8)

        def step8():
            """确认下载设置"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 确认下载设置...")
            log_debug("确认下载设置")
            self.wait_and_click("下载确定按钮:")
            parse_window_wait = int(self.parse_window_wait_time.get())
            self.wait_with_counter(parse_window_wait, step9, "等待关闭解析窗口", current_keyword)

        def step9():
            """关闭解析窗口"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 关闭解析窗口...")
            log_debug("关闭解析窗口")
            self.wait_and_click("解析窗口关闭按钮:")
            self.root.after(1000, step10)

        def step10():
            """完成处理"""
            current_keyword = get_display_keyword()
            self.status_var.set(f"开始处理关键词: {current_keyword}")
            task_completion()

            # 开始执行

        current_keyword2 = get_display_keyword()
        self.status_var.set(f"开始处理关键词: {current_keyword2}")
        self.root.update()
        self.root.after(500, step0)
        return True

    def run_software2_automation(self, keyword):
        """抖音视频下载助手的自动化流程"""

        def log_debug(message):
            """输出调试信息到文件"""
            self.log_manager.write_log(message, "软件2")

        def get_display_keyword():
            """获取用于显示的关键词"""
            return keyword[1] if isinstance(keyword, tuple) else keyword

        def task_completion():
            """任务完成后的处理"""
            self.task_running = False
            self.task_completed = True
            current_keyword1 = get_display_keyword()
            if self.alternate_execution.get():
                if len(self.current_executions[keyword]) < 2:
                    self.status_var.set(f"✓ 完成软件2处理关键词: {current_keyword1}，等待执行软件1")
                else:
                    self.status_var.set(f"✓ 两个软件都已完成处理关键词: {current_keyword1}")
            else:
                self.status_var.set(f"✓ 完成处理关键词: {current_keyword1}")
            log_debug("任务完成")

        # 记录初始信息
        log_debug(f"开始处理关键词: {keyword}")
        if isinstance(keyword, tuple):
            log_debug(f"软件2关键词: {keyword[1]}")
            log_debug(f"目录路径: {keyword[2]}")

        def step0():
            """切换窗口1"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword2 = get_display_keyword()
            self.status_var.set(f"[{current_keyword2}] 切换窗口...")
            log_debug("切换窗口")
            self.wait_and_click("切换窗口2:")
            self.root.after(1000, step1)

        def step1():
            """点击全局设置"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword3 = get_display_keyword()
            self.status_var.set(f"[{current_keyword3}] 配置全局设置...")
            log_debug("点击全局设置")
            self.wait_and_click("点击全局设置:")
            self.root.after(1000, step2)

        def step2():
            """点击更改"""
            if self.stop_flag:
                self.task_running = False
                return

            log_debug("点击更改按钮")
            self.wait_and_click("点击更改:")
            self.root.after(1000, step3)

        def step3():
            """设置下载路径"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword = get_display_keyword()
            self.status_var.set(f"[{current_keyword}] 设置下载路径...")
            self.wait_and_click("粘贴文件夹:")
            pyautogui.hotkey('ctrl', 'a')
            pyautogui.press('backspace')

            try:
                target_path = self._get_download_path(keyword)
                log_debug(f"最终路径: {target_path}")
                pyperclip.copy(target_path)
                pyautogui.hotkey('ctrl', 'v')
            except Exception as e:
                log_debug(f"路径设置错误: {str(e)}")
                raise e

            self.root.after(1000, close())

        def close():
            """关闭下拉框"""
            if self.stop_flag:
                self.task_running = False
                return

            log_debug("关闭下拉")
            self.wait_and_click("关闭下拉:")
            self.root.after(1000, step4)

        def step4():
            """选择文件夹"""
            if self.stop_flag:
                self.task_running = False
                return

            log_debug("确认文件夹选择")
            self.wait_and_click("选择文件夹:")
            self.root.after(1000, step5)

        def step5():
            """点击解析搜索"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword5 = get_display_keyword()
            self.status_var.set(f"[{current_keyword5}] 准备搜索...")
            log_debug("点击解析搜索按钮")
            self.wait_and_click("点击解析搜索:")
            self.root.after(1000, step6)

        def step6():
            """搜索关键词"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword6 = get_display_keyword()
            self.status_var.set(f"[{current_keyword6}] 输入搜索关键词...")
            self.wait_and_click("搜索框:")
            pyautogui.hotkey('ctrl', 'a')
            pyautogui.press('backspace')
            pyperclip.copy(current_keyword6)
            log_debug(f"输入搜索关键词: {current_keyword6}")
            pyautogui.hotkey('ctrl', 'v')
            self.root.after(1000, step7)

        def step7():
            """设置最大解析数量"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword7 = get_display_keyword()
            max_parse = self.max_parse_entry.get().strip() or "20"
            self.status_var.set(f"[{current_keyword7}] 设置解析数量...")
            log_debug(f"设置最大解析数量: {max_parse}")

            self.wait_and_click("最大解析数量:")
            pyautogui.hotkey('ctrl', 'a')
            pyautogui.press('backspace')
            pyperclip.copy(max_parse)
            pyautogui.hotkey('ctrl', 'v')
            self.root.after(1000, step8)

        def step8():
            """点击开始解析"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword8 = get_display_keyword()
            self.status_var.set(f"[{current_keyword8}] 开始解析...")
            log_debug("开始解析")
            self.wait_and_click("开始解析:")
            parse_wait = int(self.max_parse_wait.get().strip() or "60")
            log_debug(f"等待解析完成，时间: {parse_wait}秒")
            self.wait_with_counter(parse_wait, step9, "等待解析完成", current_keyword8)

        def step9():
            """设置筛选条件并下载"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword9 = get_display_keyword()
            self.status_var.set(f"[{current_keyword9}] 设置筛选条件...")

            # 检查是否需要设置筛选条件
            has_filters = False
            log_debug("开始设置筛选条件")

            # 辅助函数：检查并设置筛选值
            def set_filter_value(entry, field_label, filter_name):
                value = entry.get().strip()
                if value and value.isdigit() and int(value) > 0:
                    log_debug(f"设置{filter_name}: {value}")
                    self.wait_and_click(field_label)
                    pyautogui.hotkey('ctrl', 'a')
                    pyautogui.press('backspace')
                    pyperclip.copy(value)
                    pyautogui.hotkey('ctrl', 'v')
                    return True
                return False

            # 设置各项筛选条件
            if set_filter_value(self.min_likes_entry, "作品点赞数:", "最小点赞数"):
                has_filters = True
            if set_filter_value(self.min_comments_entry, "作品评论数:", "最小评论数"):
                has_filters = True
            if set_filter_value(self.min_favorites_entry, "作品收藏数:", "最小收藏数"):
                has_filters = True
            if set_filter_value(self.min_duration_entry, "作品时长秒:", "最小时长"):
                has_filters = True

            log_debug(f"是否使用筛选: {has_filters}")
            self.wait_and_click("开始筛选:")

            if has_filters:
                self.root.after(1000, lambda: step10(True))
            else:
                self.root.after(1000, lambda: step10(True))

        def step10(use_filter):
            """开始下载"""
            if self.stop_flag:
                self.task_running = False
                return

            current_keyword10 = get_display_keyword()
            self.status_var.set(f"[{current_keyword10}] 开始下载...")

            if use_filter:
                log_debug("下载筛选结果")
                self.wait_and_click("下载筛选:")
            else:
                log_debug("下载全部结果")
                self.wait_and_click("下载全部:")

            self.root.after(1000, lambda: step11())

        def step11():
            """关闭弹窗"""
            if self.stop_flag:
                self.task_running = False
                return
            log_debug("确认下载")
            self.wait_and_click("点击确认按钮:")
            self.root.after(1000, lambda: step12())

        def step12():
            """清空列表"""
            if self.stop_flag:
                self.task_running = False
                return
            log_debug("清空列表")
            self.wait_and_click("点击清空列表:")
            self.root.after(1000, lambda: step13())

        def step13():
            """点击确认按钮"""
            if self.stop_flag:
                self.task_running = False
                return

            log_debug("最终确认")
            self.wait_and_click("确认:")
            self.root.after(1000, lambda: task_completion())

        # 开始执行
        current_keyword11 = get_display_keyword()
        self.status_var.set(f"开始处理关键词: {current_keyword11}")
        self.root.update()
        self.root.after(500, step0)
        return True

    def start_batch_automation(self, auto_confirm=False):
        """
        开始批量处理
        :param auto_confirm: 是否自动确认（调度任务时为True）
        """
        if not self.keywords:
            messagebox.showerror("错误", "请先导入关键词")
            return

        # 如果是手动执行，需要确认
        if not auto_confirm and not messagebox.askyesno("确认", f"将要处理 {len(self.keywords)} 个关键词，是否继续？"):
            return

        def start_batch_process():
            self.current_batch_index = 0
            self.process_next_keyword()

        # 启动下载器
        success = self.start_downloader()
        if success:
            # 确保清除之前的倒计时状态
            self.countdown_active = False
            # 等待下载器初始化完成后开始批处理
            self.wait_for_downloader(10, start_batch_process)
        else:
            # 如果是调度任务，自动继续执行
            if auto_confirm:
                self.log_manager.write_log("下载器启动失败，但调度任务继续执行", "调度")
                start_batch_process()
            # 如果是手动执行，询问用户
            elif messagebox.askyesno("警告", "下载器启动失败，是否继续执行任务？"):
                start_batch_process()

    def process_next_keyword(self):
        """处理下一个关键词"""
        if self.stop_flag or self.current_batch_index >= len(self.keywords):
            self.status_var.set("✓ 批量处理完成！")
            # 清理执行状态记录
            self.current_executions = {}
            return

        # 获取当前关键词元组
        keyword_tuple = self.keywords[self.current_batch_index]
        total = len(self.keywords)

        # 显示当前处理的关键词信息（简化版本）
        kw1, kw2, dir_path = keyword_tuple
        current_software = self.software_var.get()
        if current_software == "software1":
            display_keyword = kw1
        else:
            display_keyword = kw2

        # 简化的状态显示
        self.status_var.set(f"任务 {self.current_batch_index + 1}/{total}: {display_keyword}")

        # 开始执行自动化任务
        success = self.start_automation(keyword_tuple)

        # 检查执行状态和更新进度
        if not self.alternate_execution.get() or (
                keyword_tuple in self.current_executions and len(self.current_executions[keyword_tuple]) == 2):
            self.update_task_list_status(self.current_batch_index, keyword_tuple, success)
            self.current_batch_index += 1

        if success:
            if self.current_batch_index < len(self.keywords):
                interval = int(self.task_interval.get())
                self.root.after(100, lambda: self.check_and_wait_for_next_task(interval))
            else:
                self.status_var.set("✓ 所有任务处理完成！")
                self.current_executions = {}
        else:
            if str(success) == "用户终止执行":
                return
            if not messagebox.askyesno("错误", f"处理关键词 '{display_keyword}' 失败。是否继续处理下一个？"):
                return
            self.current_batch_index += 1
            self.process_next_keyword()

    def wait_between_tasks(self, seconds, next_task):
        """任务之间的等待，带倒计时显示"""
        if not self.task_completed:  # 如果当前任务还未完成，不开始下一个任务
            return

        if seconds <= 0:
            self.task_completed = False  # 重置任务完成标志
            next_task()
            return

        if self.current_batch_index < len(self.keywords):
            next_keyword = self.keywords[self.current_batch_index]
            # 根据当前软件选择显示对应的关键词
            if isinstance(next_keyword, tuple):
                kw1, kw2, _ = next_keyword
                display_keyword = kw1 if self.software_var.get() == "software1" else kw2
                total = len(self.keywords)
                # 使用简化的状态显示
                self.status_var.set(
                    f"等待 {seconds}秒后执行任务 {self.current_batch_index + 1}/{total}: {display_keyword}")
            else:
                # 处理非元组情况（单个关键词）
                self.status_var.set(f"等待 {seconds}秒后执行任务: {next_keyword}")
        else:
            self.status_var.set(f"等待处理下一个任务... ({seconds}秒)")
        self.root.update()

        # 检查停止标志
        if self.stop_flag:
            self.stop_flag = False
            raise Exception("用户终止执行")

        # 使用after延迟1秒后再次调用，并减少等待时间
        self.root.after(1000, lambda: self.wait_between_tasks(seconds - 1, next_task))

    def check_and_wait_for_next_task(self, interval):
        """检查当前任务是否完成并等待下一个任务"""
        if self.task_completed and not self.task_running:
            self.wait_between_tasks(interval, self.process_next_keyword)
        else:
            self.root.after(100, lambda: self.check_and_wait_for_next_task(interval))

    def __del__(self):
        """析构函数，清理键盘监听"""
        try:
            keyboard.unhook_all()
        except:
            pass


def check_admin():
    """检查是否以管理员权限运行"""
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False


if __name__ == "__main__":
    # 检查管理员权限
    if not check_admin():
        messagebox.showwarning("警告", "建议以管理员权限运行此程序！\n否则可能无法正常控制下载器。")
        if messagebox.askyesno("提示", "是否以管理员权限重新启动程序？"):
            ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable,
                                                " ".join(sys.argv), None, 1)
            sys.exit()

    try:
        root = tk.Tk()
        app = AutoDownloaderGUI(root)
        root.mainloop()
    except Exception as e:
        with open("error_log.txt", "w", encoding='utf-8') as f:
            f.write(f"错误: {str(e)}")
        messagebox.showerror("错误", f"程序启动失败: {str(e)}")
